package cn.daniellee.plugin.rs;

import cn.daniellee.plugin.rs.command.ShopCommand;
import cn.daniellee.plugin.rs.command.ShopCompleter;
import cn.daniellee.plugin.rs.core.ShopCore;
import cn.daniellee.plugin.rs.listener.MenuListener;
import cn.daniellee.plugin.rs.model.Privilege;
import cn.daniellee.plugin.rs.model.Shop;
import cn.daniellee.plugin.rs.model.ShopItem;
import cn.daniellee.plugin.rs.storage.MysqlStorage;
import cn.daniellee.plugin.rs.storage.Storage;
import cn.daniellee.plugin.rs.storage.StorageConverter;
import cn.daniellee.plugin.rs.storage.SqliteStorage;
import com.google.gson.Gson;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;

public class RestrictedShop extends JavaPlugin {

	private static RestrictedShop instance;

	private String prefix;

	private Storage storage;

	private List<Privilege> privileges;

	public void onEnable(){
		instance = this;

		if (loadConfig()) {
			getLogger().info(" ");
			getLogger().info(">>>>>>>>>>>>>>>>>>>>>>>> RestrictedShop Loaded <<<<<<<<<<<<<<<<<<<<<<<<");
			getLogger().info(">>>>> If you encounter any bugs, please contact author's QQ: 768318841 <<<<<");
			getLogger().info(" ");

			Bukkit.getPluginManager().registerEvents(new MenuListener(), this);

			Bukkit.getPluginCommand("restrictedshop").setExecutor(new ShopCommand());
			Bukkit.getPluginCommand("restrictedshop").setTabCompleter(new ShopCompleter());
		}
	}

	public boolean loadConfig() {
		getLogger().info("[RestrictedShop]Loading config...");
		// 检查配置文件是否初始化
		if(!getDataFolder().exists()) getDataFolder().mkdirs();
		// 检查商店目录是否存在
		File shopsPath = new File(getDataFolder().getPath() + "/shops/");
		if (!shopsPath.exists()) {
			shopsPath.mkdirs();
			// 复制默认商店模板
            try {
				FileSystem fs = FileSystems.newFileSystem(getDataFolder().toPath().resolve("..").normalize().resolve(getFile().getName()), (ClassLoader) null);
                Files.copy(fs.provider().newInputStream(fs.getPath("default.yml")), shopsPath.toPath().resolve("default.yml"), StandardCopyOption.REPLACE_EXISTING);
            } catch (IOException e) {
				RestrictedShop.getInstance().getLogger().info(" ");
				RestrictedShop.getInstance().getLogger().info("[RestrictedShop]An error occurred in default shop config export.");
				RestrictedShop.getInstance().getLogger().info(" ");
				e.printStackTrace();
            }
        }
		// 尝试关闭先前的连接
		if (storage != null) storage.close();
		// 加载存储
		storage = getConfig().getBoolean("storage.mysql.use", false) ? new MysqlStorage() : new SqliteStorage();
		if (storage.initialize()) {
			getLogger().info("[RestrictedShop]Storage initialized.");
		} else {
			getLogger().info(" ");
			getLogger().info("[RestrictedShop]Initializing data store failed, please edit the config and reload the plugin.");
			getLogger().info(" ");
			Bukkit.getPluginManager().disablePlugin(this);
			return false;
		}
		if (getConfig().getBoolean("storage.mysql.use", false) && getConfig().getBoolean("storage.mysql.convert", false)) {
			SqliteStorage sqliteStorage = new SqliteStorage();
			if (sqliteStorage.initialize()) {
				StorageConverter converter = new StorageConverter(sqliteStorage, (MysqlStorage) storage);
				converter.execute();
				getConfig().set("storage.mysql.convert", false);
				saveConfig();
				getLogger().info("[RestrictedShop]Successfully transferred Yaml data to Mysql.");
			} else {
				getLogger().info(" ");
				getLogger().info("[RestrictedShop]Yaml data store initialization failed, data conversion canceled.");
				getLogger().info(" ");
			}
		}
		prefix = "&7[&6" + getConfig().getString("prompt-prefix", "RestrictedShop") + "&7] &3: &r";
		privileges = getConfig().getMapList("setting.privileges").stream().map(item -> {
			Privilege privilege = new Privilege();
			privilege.setSuffix((String) item.get("suffix"));
			privilege.setPercentage((int) item.get("percentage"));
			return privilege;
		}).collect(Collectors.toList());
		saveDefaultConfig();
		// 加载商店配置文件
		loadShops(shopsPath);
		return true;
	}

	private void loadShops(File shopsPath) {
		ShopCore.SHOPS.clear();
		if (shopsPath.isDirectory()) {
			// 读取shops目录下所有yml文件
			File[] shops = shopsPath.listFiles();
			if (shops != null) {
				// 依次获取商店信息
				Arrays.stream(shops).forEach(shopFile -> {
					try {
						if (shopFile.getName().endsWith(".yml")) {
							FileConfiguration shopConfig = new YamlConfiguration();
							shopConfig.load(shopFile);
							// 读取商店信息并解析商品列表，过滤配置错误的商品
							Shop shop = new Shop();
							shop.setName(shopFile.getName().replace(".yml", ""));
							shop.setTitle(shopConfig.getString("title", "&bPurchase Shop"));
							shop.setMaxShowNumber(shopConfig.getInt("max-show-number", 3));
							shop.setPayTemplate(shopConfig.getString("pay-template", "money give {player} {amount}"));
							shop.setCurrencyName(shopConfig.getString("currency-name", "&e金币"));
							shop.setRefreshInterval(shopConfig.getLong("refresh-interval", 24) * 3600000);
							shop.setPurchaseItems(shopConfig.getMapList("purchase-items").stream().map(item -> {
								ShopItem shopItem = new ShopItem();
								shopItem.setMaterial((String) item.get("material"));
								shopItem.setCustomerModelData((int) item.get("customer-model-data"));
								shopItem.setDisplayName((String) item.get("display-name"));
								shopItem.setPriceRange(((List<Integer>) item.get("price-range")).toArray(new Integer[]{}));
								shopItem.setQuantityRange(((List<Integer>) item.get("quantity-range")).toArray(new Integer[]{}));
								shopItem.setWeight((int) item.get("weight"));
								return shopItem;
							})
								.filter(item -> item.getPriceRange() != null && item.getQuantityRange() != null && item.getPriceRange().length == 2 && item.getQuantityRange().length == 2 && item.getPriceRange()[1] >= item.getPriceRange()[0] && item.getQuantityRange()[1] >= item.getQuantityRange()[0])
									.collect(Collectors.toList()));
							// 计算商品列表的校验和
							shop.setCheckSum(Base64.getEncoder().encodeToString(MessageDigest.getInstance("MD5").digest(new Gson().toJson(shop.getPurchaseItems()).getBytes(StandardCharsets.UTF_8))));
							ShopCore.SHOPS.put(shop.getName(), shop);
						}
					} catch (Exception e) {
						getLogger().info(" ");
						getLogger().info("[RestrictedShop]Failed to load shop: " + shopFile.getName());
						getLogger().info(" ");
						e.printStackTrace();
					}
				});
			}

		}

	}

	@Override
	public void onDisable() {
		getLogger().info(" ");
		getLogger().info(">>>>>>>>>>>>>>>>>>>>>>>> RestrictedShop Unloaded <<<<<<<<<<<<<<<<<<<<<<<<");
		getLogger().info(" ");
	}

	public static RestrictedShop getInstance() {
		return instance;
	}

	public String getPrefix() {
		return prefix;
	}

	public Storage getStorage() {
		return storage;
	}

	public List<Privilege> getPrivileges() {
		return privileges;
	}
}
